#pragma once

#include <cv.h>

#define WHITE 255
#define BLACK 0

#include <queue>
using std::queue;

static bool getStartingPoint( IplImage *image, CvPoint& startingPoint , int colorThresholdLow , int colorThresholdHigh , bool reset );

/***************************** Function At The End **************************************

Function : isThereBigObject( IplImage *image, int widthThreshold , int heightThreshold , 
		   int colorThresholdLow , int colorThresholdHigh )
Input : Image, Thresholds
Output : The function will return true if it has found an object of colors in between 
the greyscale color threshold that is big enough - in "limiting box" defined by its 
top-left bottom-right corners exceeds the thresholds - that is bigger than 
wifth and height thresholds.

*****************************************************************************************/

/********************************* Current Step ******************************************

The function will now be able to find big enough objects between color thresholds 
and will work on all greyscale.

*****************************************************************************************/

bool isThereBigObject( IplImage *image, int widthThreshold , int heightThreshold  , int colorThresholdLow , int colorThresholdHigh ){
	
	image = cvCloneImage(image);
	CvPoint startingPoint;

	getStartingPoint(image,startingPoint,colorThresholdLow,colorThresholdHigh,true); //reseting

	while( getStartingPoint(image,startingPoint,colorThresholdLow,colorThresholdHigh,false) ){
		queue<CvPoint> qPoints;
		qPoints.push(startingPoint);
		CvPoint topLeft = startingPoint, bottomRight = startingPoint; // bounding box
		while (!qPoints.empty()) {
			CvPoint currentPoint(qPoints.front()); 
			qPoints.pop();

			if( ((uchar*)image->imageData + image->widthStep*currentPoint.y)[currentPoint.x] < colorThresholdLow ||
				((uchar*)image->imageData + image->widthStep*currentPoint.y)[currentPoint.x] > colorThresholdHigh ) continue;

			((uchar*)image->imageData + image->widthStep*currentPoint.y)[currentPoint.x] = 0;

			// getting the bounding box:
			if (currentPoint.x < topLeft.x)
				topLeft.x = currentPoint.x;
			if (currentPoint.y > topLeft.y)
				topLeft.y = currentPoint.y;
			if (currentPoint.x > bottomRight.x)
				bottomRight.x = currentPoint.x;
			if (currentPoint.y < bottomRight.y)
				bottomRight.y = currentPoint.y;

			// doing the bfs action, basically:
			if (currentPoint.x > 0)
				qPoints.push( cvPoint(currentPoint.x - 1, currentPoint.y) );
			if (currentPoint.x + 1 < image->width)
				qPoints.push( cvPoint(currentPoint.x + 1, currentPoint.y) );
			if (currentPoint.y > 0)
				qPoints.push( cvPoint(currentPoint.x, currentPoint.y - 1) );
			if (currentPoint.y + 1 < image->height)
				qPoints.push( cvPoint(currentPoint.x, currentPoint.y + 1) );
		}
		CvSize objectSize = cvSize( bottomRight.x - topLeft.x, topLeft.y - bottomRight.y );
		if( (objectSize.width*100/image->width) >= widthThreshold && (objectSize.height*100/image->height) >= heightThreshold ) return true;
	}

	return false;
}


static bool getStartingPoint( IplImage *image, CvPoint& startingPoint , int colorThresholdLow , int colorThresholdHigh , bool reset ){ //goes over image and always get a new starting point in threshold limits , gets grayscale image , should be reset between images

	static int currentX;
	static int currentY;

	if(reset){
		currentX = currentY = 0;
		return true;
	}

	for( ; currentX < image->width ; ++currentX ){
		for( ; currentY < image->height ; ++currentY ){
			if( ((uchar*)image->imageData + image->widthStep*currentY)[currentX] < colorThresholdLow ||
				((uchar*)image->imageData + image->widthStep*currentY)[currentX] > colorThresholdHigh ) continue;
			else{
				startingPoint.x = currentX;
				startingPoint.y = currentY;
				++currentY;
				return true;
			}
		}
		currentY = 0;
	}
	return false;
}
